import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.awt.Polygon;

import java.util.Locale;
import java.util.Random; 



import pluginUtils.Circle;
import pluginUtils.Complexe; 
import pluginUtils.MobiusTransform;


public class IndraPearls extends ImagePlus implements PlugIn{
	{Locale.setDefault(Locale.US); }
	
	private ImageProcessor primeIP; 
	private int X=2000,Y=2000; // image size
	
	private Random generator=new Random(); // One always needs some randomness
	
	// For the scaling of the image
	private double x0=0,x1=1,y0=0,y1=1;
	private double acoef,ccoef,vcoef,wcoef; 
	
	
	
	public void setCoefs(){
		acoef=X/(x1-x0); 
		vcoef=Y/(y1-y0); 
		ccoef=-acoef*x0; 
		wcoef=-vcoef*y0; 
	}
	 
	
	
	public void setBounds(double xl,double xu,double yl,double yu){
		x0=xl; 
		x1=xu;
		y0=yl;
		y1=yu; 
	}
	
	
	private static double altitude=10; 
	
	
	private void drawCircle(Circle c){
		double xCenter=c.getCenter().getReal(); 
		double yCenter=c.getCenter().getIm(); 
		
		
		int intX=(int)(xCenter*acoef+ccoef);
		int intY=(int)(yCenter*vcoef+wcoef);
		int intRx=(int)(c.getRadius()*acoef);
		int intRy=(int)(c.getRadius()*vcoef);
		
		primeIP.drawOval(intX-intRx,intY-intRy,intRx*2,intRy*2);
		String s="sphere{\n<"+xCenter+","+yCenter+","+altitude+">,";
		s+=c.getRadius(); 
		s+=" texture{pigment {color Yellow } finish {reflection 0.5 specular 0.7} }"; 
		System.out.println(s); 
		altitude*=0.5;
		
	}
	
	private void drawPoint(Complexe c){
		double xCenter=c.getReal(); 
		double yCenter=c.getIm(); 
		int intX=(int)(xCenter*acoef+ccoef);
		int intY=(int)(yCenter*vcoef+wcoef);
		primeIP.fillOval(intX-10,intY-10,20,20);
	}
	
	
	
	
	
	private void drawLine(double xd,double yd,double xf,double yf){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		primeIP.drawLine(XD,YD,XF,YF); 
	}
	
	
	
	public void run(String arg) {
		primeIP = new ColorProcessor(X,Y);
		
		
		
	
		setBounds(-30,30,-30,30); 
		setCoefs(); 
		
		
		
		
		
		
		Polygon background=new Polygon(new int[]{0,0,X,Y},new int[]{0,X,Y,0},4);
		primeIP.setColor(Color.WHITE);
		
		primeIP.fillPolygon(background);
		
		
		primeIP.setFont(new Font(null,Font.ITALIC,60));
		primeIP.setColor(Color.BLACK);
		primeIP.setLineWidth(5); 
		
		
		Complexe a=Complexe.createComplexeFromRI(Math.sqrt(3)/2,0.5);
		Complexe b=Complexe.createComplexeFromRI(0,5.1); 
		Complexe c=Complexe.createComplexeFromRI(0,0);
		Complexe d=Complexe.createComplexeFromRI(1.12,0); 
		MobiusTransform testTrans=new MobiusTransform(a,b,c,d); 
		System.out.println("***\n"+testTrans+"\n***"); 
		drawLine(x0,0,x1,0);
		drawLine(0,y0,0,y1);
	
		setProcessor("Verifying", primeIP);
		Complexe center=Complexe.createComplexeFromRI(10,0); 
		Circle testOne=new Circle(center,5); 
		
		for(int i=0;i<50;i++){
		drawCircle(testOne); 
		drawPoint(testOne.getCenter()); 
		testOne=testTrans.circleImage(testOne);
		}
		
		
		
	
		
		
		show();
		System.out.println("done "); 
	}	
}
	